
#include "pathparser.h"
#include "config.h"
#include "utils/string.h"
#include "memory/memory.h"
#include "memory/heap/kheap.h"
#include "status.h"

#define OUT

// TESTOS_STATUS_BAD_PATH

static const int pathparser_path_valid_format(const char* path)
{
    const int len = strlen(path); 

    return len >= 3 
        && len <= TESTOS_MAX_PATH_SIZE
        && is_digit(path[0]) 
        && memcmp((void*)(path + 1), ":/", 2) == 0; 
}

static const int pathparser_get_drive_by_path(const char* path, OUT const char** next)
{
    // next -> 0:/a/text.txt to a/text.txt

    *next = path + 3; // path + length of '0:/' (3 chars)
    return to_numeric_digit(*path);  
}

static struct path_root* pathparser_create_root(const int drive_no)
{
    struct path_root* ret = (struct path_root*)kzalloc(sizeof(struct path_root)); 
    ret->drive_no = drive_no; 
    ret->first = 0; 
    return ret; 
}

static const char* pathparser_get_path_part(const char* path, OUT const char** next)
{
    char* result_path_part = (char*)kzalloc(TESTOS_MAX_PATH_SIZE);
    int i = 0; 
    while (*path != '/' && *path != 0) {
        result_path_part[i] = *path; 
        path++; 
        i++; 
    } 

    if (*path == '/') {
        // Skip the '/' to avoid infinite loop
        *next = path + 1;
    }
    else {
        *next = path; 
    }

    if (i == 0) {
        kfree(result_path_part); 
        result_path_part = 0; 
    }

    return result_path_part; 
}

static struct path_part* pathparser_parse_path_part(struct path_part* last_part, const char* path, OUT const char **next) 
{
    const char* path_part_str = pathparser_get_path_part(path, OUT next); 
    if (!path_part_str) {
        return 0; 
    }

    struct path_part* part = (struct path_part*)kzalloc(sizeof(struct path_part));
    part->part = path_part_str; 
    part->next = 0x00; 

    if (last_part) {
        last_part->next = part; 
    }

    return part; 
}

void pathparser_free(struct path_root* root) 
{
    struct path_part* part = root->first; 
    struct path_part* next = 0; 
    while (part) {
        next = part->next; 
        kfree((void*)part->part); 
        kfree((void*)part); 
        part = next;
    }

    kfree(root); 
}

struct path_root* pathparser_parse(const char* path, const char* current_directory_path)
{
    int res = 0; 
    const char* tmp_path = path; 
    const char* next = 0; 
    struct path_root* path_root = 0; 

    if (!pathparser_path_valid_format(tmp_path)) {
        goto out; 
    }

    res = pathparser_get_drive_by_path(tmp_path, OUT &next);
    if (res < 0) {
        goto out; 
    }
    tmp_path = next; 

    path_root = pathparser_create_root(res);
    if (!path_root) {
        goto out; 
    }

    struct path_part* first_part = pathparser_parse_path_part(0, tmp_path, OUT &next); 
    if (!first_part) {
        goto out; 
    }
    tmp_path = next; 
    path_root->first = first_part; 

    struct path_part* part = pathparser_parse_path_part(first_part, tmp_path, OUT &next); 
    while (part) {
        tmp_path = next; 
        
        part = pathparser_parse_path_part(part, tmp_path, OUT &next); 
    }

out:
    return path_root; 
}

